package com.example.demo.user.controller;

import com.example.demo.common.BaseResponse;
import com.example.demo.common.PageResult;
import com.example.demo.common.ResultUtils;
import com.example.demo.config.security.JwtTokenService;
import com.example.demo.config.security.UserPrincipal;
import com.example.demo.user.dto.UserCreateRequest;
import com.example.demo.user.dto.UserLoginRequest;
import com.example.demo.user.dto.UserLoginResponse;
import com.example.demo.user.dto.UserQueryRequest;
import com.example.demo.user.dto.UserQuotaUpdateRequest;
import com.example.demo.user.dto.UserResponse;
import com.example.demo.user.dto.UserUpdateRequest;
import com.example.demo.user.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 用户控制器,提供登录注册与基础 CRUD 接口。
 * 需要启用数据库功能才能使用 (feature.database.enabled=true)
 */
@RestController
@RequestMapping("/users")
@RequiredArgsConstructor
@Validated
@ConditionalOnProperty(prefix = "feature.database", name = "enabled", havingValue = "true", matchIfMissing = false)
@Tag(name = "用户管理", description = "提供用户注册、登录以及增删改查接口")
public class UserController {

    private final UserService userService;
    private final AuthenticationManager authenticationManager;
    private final JwtTokenService jwtTokenService;

    @PostMapping("/register")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "注册新用户", description = "创建新的用户账号，返回用户基本信息")
    public BaseResponse<UserResponse> register(@RequestBody @Valid UserCreateRequest request) {
        return ResultUtils.success(userService.register(request));
    }

    @PostMapping("/login")
    @Operation(summary = "用户登录", description = "校验用户名与密码，返回用户信息与令牌")
    public BaseResponse<UserLoginResponse> login(@RequestBody @Valid UserLoginRequest request) {
        Authentication authentication = authenticationManager.authenticate(
                new UsernamePasswordAuthenticationToken(request.getUsername(), request.getPassword()));
        UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
        return ResultUtils.success(buildLoginResponse(principal));
    }

    @GetMapping
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "查询用户列表", description = "支持分页及关键字搜索")
    public BaseResponse<PageResult<UserResponse>> list(@Valid @ModelAttribute UserQueryRequest request) {
        return ResultUtils.success(userService.listUsers(request));
    }

    @PostMapping("/refresh")
    @PreAuthorize("hasAnyRole('ADMIN','USER')")
    @Operation(summary = "刷新令牌", description = "使用有效 JWT 换取新的 JWT")
    public BaseResponse<UserLoginResponse> refresh(Authentication authentication) {
        UserPrincipal principal = (UserPrincipal) authentication.getPrincipal();
        return ResultUtils.success(buildLoginResponse(principal));
    }

    @GetMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "查询用户详情", description = "根据用户 ID 返回对应的详细信息")
    public BaseResponse<UserResponse> detail(@PathVariable Long id) {
        return ResultUtils.success(userService.getUser(id));
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "更新用户信息", description = "支持修改昵称或密码")
    public BaseResponse<UserResponse> update(@PathVariable Long id,
                                             @RequestBody @Valid UserUpdateRequest request) {
        return ResultUtils.success(userService.updateUser(id, request));
    }

    @PutMapping("/{id}/quota")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "配置用户 ZIP 配额", description = "管理员为普通用户分配或调整 ZIP 生成次数")
    public BaseResponse<UserResponse> updateQuota(@PathVariable Long id,
                                                  @RequestBody @Valid UserQuotaUpdateRequest request) {
        return ResultUtils.success(userService.updateZipQuota(id, request.getZipQuota(), request.getZipUsed()));
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    @Operation(summary = "删除用户", description = "根据用户 ID 删除账号")
    public BaseResponse<Boolean> delete(@PathVariable Long id) {
        userService.deleteUser(id);
        return ResultUtils.success(Boolean.TRUE);
    }

    private UserLoginResponse buildLoginResponse(UserPrincipal principal) {
        List<String> roles = principal.getAuthorities().stream()
                .map(GrantedAuthority::getAuthority)
                .collect(Collectors.toList());
        String token = jwtTokenService.generateToken(principal.getId(), principal.getUsername(), Map.of("roles", roles));
        return UserLoginResponse.builder()
                .token(token)
                .user(userService.getUser(principal.getId()))
                .build();
    }
}
